<?php

namespace App\Http\Controllers\Counter;

use App\Enums\Notification\CounterApply;
use App\Enums\OrderItemType;
use App\Enums\PayChannel;
use App\Enums\TableStatus;
use App\Enums\TradeStatus;
use App\Helper\ApiResponseHelper;
use App\Helper\SmsCode;
use App\Http\Controllers\Controller;
use App\Http\Requests\Counter\OrdersBillRequest;
use App\Http\Requests\Counter\OrdersCheckRequest;
use App\Http\Resources\Counter\OnlineTradeOrderResource;
use App\LeShua\LeShua;
use App\Models\Member;
use App\Models\OnlineTradeOrder;
use App\Models\Order;
use App\Models\OrderItem;
use App\Models\StoreNotification;
use App\Models\Table;
use App\Structs\OrderBill;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\DB;

class OrdersController extends Controller
{
    public function notifyClearOrder(Order $order)
    {
        if (!in_array($order->status, [TradeStatus::Created, TradeStatus::Pending, TradeStatus::PendingOpen]))
            return ApiResponseHelper::json([], 400, '订单状态不正确');

        StoreNotification::create([
            'store_id' => $order->store_id,
            'type' => 'counter_apply',
            'notification_name' => CounterApply::CartClear,
            'model_id' => $order->id,
            'need_action' => true,
            'operator_user_id' => Auth::id(),
        ]);

        return ApiResponseHelper::json([]);
    }

    public function ordersCheck(OrdersCheckRequest $request, SmsCode $smsCode)
    {
        $type = PayChannel::from($request->type);
        $orderIds = $request->order_ids;
        $barCode = $request->bar_code;
        $finishDate = $request->finish_date;
        //是否抹零
        $noYuan = $request->input('no_yuan') == 'true';
        $noJiao = $request->input('no_jiao') == 'true';
        $noFen = $request->input('no_fen') == 'true';

        //检查会员
        /**
         * @var Member $card
         */
        $card = null;
        if ($type == PayChannel::Member) {

            /**
             * @var Member $card
             */
            $card = Member::withPhone($request->bar_code)->first();
            if (empty($card))
                return ApiResponseHelper::json([], 400, '会员卡不存在');

            if (!empty($request->sms_code)) {

                if (!$smsCode->verify($request->bar_code, $request->sms_code))
                    return ApiResponseHelper::json([], 400, '验证码错误');

            } else {
                if (!$card->checkPassword($request->password))
                    return ApiResponseHelper::json([], 400, '会员卡密码错误');
            }
        }

        // 查出所有订单
        $orders = Order::with([
            'items', 'items.goods', 'items.table.tableType', 'items.costRule', 'items.assistantUser',
            'user', 'member', 'store',
        ])->whereIn('id', $orderIds)->get();

        foreach ($orders as $order) {
            try {
                $this->orderCheck($order);
            } catch (\Exception $exception) {
                return ApiResponseHelper::json([], 400, $exception->getMessage());
            }
        }

        try {
            DB::transaction(function () use ($card, $type, $orders, $barCode, $finishDate, $noYuan, $noJiao, $noFen, &$tradeOrder) {

                $totalMoney = 0;
                $discountMoney = 0;
                $orderIds = [];
                /**
                 * @var Order $order
                 */
                foreach ($orders as $order) {

                    $orderIds[] = $order->id;
                    $tableItem = $order->getTableItem();

                    //是台桌订单
                    if (!empty($tableItem) && !in_array($order->status, [TradeStatus::Pending, TradeStatus::PendingOpen])) {
                        $this->finishTableItem($tableItem, $finishDate);
                    }

                    //更新订单
                    $order->pay_channel = $type;
                    $order->sumMoney();
                    if ($type == PayChannel::Member) {
                        $order->member_id = $card->id;
                        $card->orderCheck($order, Auth::user(), '会员卡支付');
                    }
                    $order->save();

                    $totalMoney += $order->money;
                }

                if ($noYuan) {
                    $newTotalMoney = $this->noYuan($totalMoney);
                    $discountMoney += $newTotalMoney - $totalMoney;
                    $totalMoney = $newTotalMoney;
                }

                if ($noJiao) {
                    $newTotalMoney = $this->noJiao($totalMoney);
                    $discountMoney += $newTotalMoney - $totalMoney;
                    $totalMoney = $newTotalMoney;
                }

                if ($noFen) {
                    $newTotalMoney = $this->noFen($totalMoney);
                    $discountMoney += $newTotalMoney - $totalMoney;
                    $totalMoney = $newTotalMoney;
                }

                if ($discountMoney != 0) {
                    $orderCount = count($orders);
                    //均分抹零金额
                    $avgDiscountMoney = $discountMoney / $orderCount;
                    foreach ($orders as $order) {
                        $order->money -= $avgDiscountMoney;
                        $order->discount_money += $avgDiscountMoney;
                        $order->save();
                    }
                }

                //开始支付
                if ($type == PayChannel::LeShua) {

                    /**
                     * @var OnlineTradeOrder $tradeOrder
                     */
                    $tradeOrder = OnlineTradeOrder::create([
                        'order_no' => OnlineTradeOrder::genOrderNo(),
                        'order_ids' => $orderIds,
                        'total_money' => $totalMoney,
                        'status' => TradeStatus::Created,
                        'store_id' => Auth::user()->store_id,
                    ]);

                    $store = $order->store;
                    $payment = new LeShua($store->leshua_num);
                    $response = $payment->scanPay($barCode, $tradeOrder->order_no, $totalMoney * 100);

                    if ($response->getStatus() == 2)
                        $tradeOrder->payed();
                    else
                        $tradeOrder->wait();
                }

                if (in_array($type, [PayChannel::Member, PayChannel::Cash, PayChannel::Bad, PayChannel::MeiTuan, PayChannel::DouYin,])) {
                    Order::orderIdsPayed($orderIds, $type);
                }
            });

            //所有完成再清验证码
            if ($type == PayChannel::Member) {
                $smsCode->verifyAndClean($request->bar_code, $request->sms_code);
            }

            if ($type == PayChannel::LeShua)
                return new OnlineTradeOrderResource($tradeOrder);

            return ApiResponseHelper::json([]);
        } catch (\Exception $exception) {
            return ApiResponseHelper::json([], 400, $exception->getMessage());
        }
    }

    public function ordersBill(OrdersBillRequest $request)
    {
        $orders = Order::with([
            'items', 'items.goods', 'items.table.tableType', 'items.costRule', 'items.assistantUser',
            'user', 'member', 'store',
        ])->whereIn('id', $request->order_ids)->get();
        $finishDate = $request->finish_date;

        if (!empty($request->member_id)) {

            $member = Member::find($request->member_id);
            if (!empty($member)) {
                foreach ($orders as $order) {
                    $order->member_id = $member->id;
                    $order->save();
                }
            }
        }

        try {

            $noYuan = $request->no_yuan == 'true';
            $noJiao = $request->no_jiao == 'true';
            $noFen = $request->no_fen == 'true';
            $discountMoney = 0;

            $orderBill = new OrderBill();
            foreach ($orders as $order) {
                $orderBill->addOrder($order, $finishDate);
            }

            $totalMoney = $orderBill->getTotalMoney();

            if ($noYuan) {
                $newTotalMoney = $this->noYuan($totalMoney);
                $discountMoney += $newTotalMoney - $totalMoney;
                $totalMoney = $newTotalMoney;
            }

            if ($noJiao) {
                $newTotalMoney = $this->noJiao($totalMoney);
                $discountMoney += $newTotalMoney - $totalMoney;
                $totalMoney = $newTotalMoney;
            }

            if ($noFen) {
                $newTotalMoney = $this->noFen($totalMoney);
                $discountMoney += $newTotalMoney - $totalMoney;
                $totalMoney = $newTotalMoney;
            }

            $orderBill->discount($discountMoney);

            return ApiResponseHelper::json($orderBill);

        } catch (\Exception $exception) {
            return ApiResponseHelper::json([], 400, $exception->getMessage());
        }
    }

    private function orderCheck(Order $order)
    {
        if (!$order->status->canPay())
            throw new \Exception('当前订单已支付，无法结算');

        foreach ($order->items as $item) {
            //判断是否有未结算的助教
            if ($item->type == OrderItemType::Assistant && $item->end_at == null)
                throw new \Exception('订单有未结算的助教');
        }
    }

    private function finishTableItem(OrderItem $tableItem, $finishDate)
    {
        /**
         * @var Table $table
         */
        $table = $tableItem->table;

        // 先解除暂停
        $table->unpause();

        if (!$table->status->isVirtual())
            $tableTotalMoney = $table->getTableTotalMoney($finishDate);
        else
            $tableTotalMoney = 0;

        //更新台桌item
        $tableItem->end_at = $finishDate;
        $tableItem->money = $tableTotalMoney;
        $tableItem->origin_money = $tableTotalMoney;
        $tableItem->save();

        //更新台桌
        $table->status = TableStatus::Idle;
        $table->table_order_id = null;
        $table->use_start_at = null;
        $table->save();
    }

    private function noYuan($total)
    {
        $integerPart = floor($total); // 获取整数部分
        $decimalPart = $total - $integerPart; // 获取小数部分
        return floor($integerPart / 10) * 10 + $decimalPart;
    }

    private function noJiao($total)
    {
        // 获取整数部分
        $integerPart = floor($total);

        // 获取小数部分
        $decimalPart = $total - $integerPart;

        if ($decimalPart == 0) {
            // 如果没有小数部分，直接返回原来的数字
            return $total;
        }

        // 将小数部分转换为字符串，并将第一位设为0
        $decimalStr = (string)$decimalPart;
        $decimalStr[2] = '0'; // 小数点后的第一位为字符串的第三位

        // 将字符串转换回浮点数
        $newDecimalPart = (float)$decimalStr;

        // 组合整数部分和新的小数部分
        $newTotal = $integerPart + $newDecimalPart;

        return $newTotal;
    }

    private function noFen($total)
    {
        // 获取整数部分
        $integerPart = floor($total);

        // 获取小数部分
        $decimalPart = $total - $integerPart;

        if ($decimalPart == 0) {
            // 如果没有小数部分，直接返回原来的数字
            return $total;
        }

        // 将小数部分放大100倍，便于操作第二位
        $decimalPart = $decimalPart * 100;

        // 获取放大后的整数部分
        $decimalIntPart = floor($decimalPart);

        // 将第二位设为0
        $decimalIntPart = floor($decimalIntPart / 10) * 10;

        // 还原小数部分
        $newDecimalPart = $decimalIntPart / 100;

        // 组合整数部分和新的小数部分
        $newTotal = $integerPart + $newDecimalPart;

        return $newTotal;
    }
}
